﻿#pragma warning(disable:4005)
#include <drogon/HttpController.h>
#include "OCMain/Environment.h"
#include "OCMain/StringUtil.h"
#include "OCMain/bcrypt/bcrypt.h"
#include "OCMain/bcrypt/base64.h"
#include "OCServer/ServerUtil.h"
#include "User.h"

using namespace OCPP;
using namespace drogon;
using namespace drogon::orm;
using namespace drogon_model;

class login : public HttpController<login>
{
public:
    METHOD_LIST_BEGIN
        METHOD_ADD(login::login1, "", { Post});
    METHOD_LIST_END
protected:
    bool checkPassword(String user,String ticket,String aesEncryptText,String passwordBcrypt)
    {
        String password = ServerUtil::AES_Decode(user + ticket, aesEncryptText);
        return bcrypt::validatePassword(password, passwordBcrypt);
    }

    String encryptLogin(String user, String ticket,String jsonStr)
    {
        return ServerUtil::AES_Encode(user + ticket, jsonStr);
    }

    String getRedis() {
        drogon::nosql::RedisClientPtr redisClient = drogon::app().getRedisClient();
        if (redisClient) {
            try
            {
                //std::ifstream ifs("E:\\volume\\png\\ANI_IR1_R04_20211004_2300_FY2G.AWX.png", std::ios::binary);

                //ifs.seekg(0, std::ios::end);
                //size_t size = ifs.tellg();
                //ifs.seekg(0);

                //String data;
                //data.resize(size);
                //ifs.read(data.data(), size);

                //String buffer = StringUtil::encodeBase64(data);

                String key = "k2";
                //{
                //    String res = redisClient->execCommandSync<String>(
                //        [](const drogon::nosql::RedisResult& r) {
                //            return r.asString();
                //        },
                //        "set %s %s", key.data(), buffer.data());
                //}

                String res = redisClient->execCommandSync<String>(
                    [](const drogon::nosql::RedisResult& r) {
                        if (r.isNil()) {
                            return String("");
                        }
                        else {
                            return r.asString();
                        }
                    },
                    "get %s", key.data());

                LOG_INFO << key << "[" << res << "]\n";
            }
            catch (const drogon::nosql::RedisException& err)
            {
                LOG_ERROR << err.what() << "\n";
            }
            catch (const std::exception& err)
            {
                LOG_ERROR << err.what() << "\n";
            }
        }
        return "";
    }

    void login1(const HttpRequestPtr& req,
        std::function<void(const HttpResponsePtr&)>&& callback)
    {
        HttpResponsePtr resp = HttpResponse::newHttpResponse();
        try {
            //getRedis();
            auto jsonObject = req->getJsonObject();
            if (jsonObject) {
                std::shared_ptr<DbClient> dbClient = drogon::app().getDbClient("mysql");
                if (dbClient) {
                    String user = (*jsonObject)["user"].asString();
                    String ticket = (*jsonObject)["ticket"].asString();
                    String data = (*jsonObject)["data"].asCString();
                    if (!user.empty() && !ticket.empty() && !data.empty()) {
                        Mapper<lotda::User> mp(dbClient);
                        auto results = mp.findOne(Criteria("name", CompareOperator::EQ, user));
                        String passwordBcrypt = *results.getPassword();
                        
                        bool success = checkPassword(user, ticket, data, passwordBcrypt);

                        String role;

                        if (success) {
                            role = *results.getRole();
                        }

                        Json::Value resJson;
                        resJson["login"] = success;
                        resJson["role"] = role;
                        resp->setBody(encryptLogin(user, ticket, resJson.toStyledString()));
                    }
                }
                else 
                {
                    LOG_ERROR << "没有配置mysql数据库\n";
                }
            }
        }
        catch (UnexpectedRows e) {
            LOG_ERROR << e.what();
        }

        callback(resp);
    }
};